package it.polimi.swKnights.SWIMv2.servlets.profile;

import it.polimi.swKnights.SWIMv2.ejb.exceptions.InvalidLoginPrivilegesException;
import it.polimi.swKnights.SWIMv2.ejb.exceptions.LoginFailException;
import it.polimi.swKnights.SWIMv2.ejb.modifyData.ModifyDataBeanRemote;
import it.polimi.swKnights.SWIMv2.general.Errors;
import it.polimi.swKnights.SWIMv2.general.FileImageManager;
import it.polimi.swKnights.SWIMv2.general.WebsiteParameters;
import it.polimi.swKnights.SWIMv2.servlets.SwimServlet;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;

/**
 * Servlet implementation class ModifyDataController
 */
public class ModifyDataController extends SwimServlet
{
	public static final long serialVersionUID = 1L;

	private Map<String, String> parametersMap = new HashMap<String, String>();

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException
	{
		HttpSession session = request.getSession();
		String username = (String) session.getAttribute("userName");
		String password = (String) session.getAttribute("password");

		try
		{
			this.processRequest(request, response);
		}
		catch (FileUploadException e1)
		{

			response.sendRedirect("./modify?error=" + e1.getMessage());
			return;
		}

		ModifyDataBeanRemote modBean = this.lookUp(ModifyDataBeanRemote.class);

		try
		{
			modBean.modifyUserData(username, password,
					parametersMap.get("name"), parametersMap.get("surname"),
					parametersMap.get("email"), parametersMap.get("sex"),
					parametersMap.get("birthday"),
					parametersMap.get("address"),

					parametersMap.get("password"),
					parametersMap.get("password_confirm"),
					parametersMap.get("City"), parametersMap.get("Street"),
					parametersMap.get("Number")

			);

			modBean.modifyUserImage(username, password,
					parametersMap.get("image"));

			if (parametersMap.get("visibility") != null)
			{
				boolean isPublic = parametersMap.get("visibility")
						.equals("Yes") ? true : false;
				modBean.modifyVisibility(username, password, isPublic);
			}

			response.sendRedirect("./Profile?username=" + username);
		}
		catch (LoginFailException e)
		{
			response.sendRedirect("./siteHome?error=" + Errors.session);
		}
		catch (InvalidLoginPrivilegesException e)
		{
			response.sendRedirect("./userHome?error=" + Errors.session);
		}

	}

	private void processRequest(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException,
			FileUploadException
	{

		ServletFileUpload uploader = new ServletFileUpload(
				new DiskFileItemFactory());
		List<?> multipartList = uploader.parseRequest(request);

		for (Object part : multipartList)
		{
			FileItem item = (FileItem) part;
			if (item.isFormField())
			{
				this.processFormField(request, item);
			}
			else
			{
				this.processFileField(item);
			}
		}

	}

	private void processFileField(FileItem item) throws FileUploadException
	{

		String fieldName = item.getFieldName();
		String fileName = this.checkSizeAndExistency(item);

		if (fileName == null)
		{
			// if no file uploaded do nothing
			return;
		}

		String prefix = FilenameUtils.getBaseName(fileName);
		String suffix = "." + FilenameUtils.getExtension(fileName);
		String path = getServletContext().getRealPath("/profileImages");
		String extension = FilenameUtils.getExtension(fileName);

		try
		{

			// default store directory is /tmp can throw IOException
			File tmpFile = File.createTempFile(prefix, suffix);
			item.write(tmpFile);
			try
			{
				FileImageManager imageManager = new FileImageManager(tmpFile);
				// where the actual stored file is located with it's name
				String storedPath = path + "/" + fileName;

				BufferedImage img = imageManager.resizeImage(
						WebsiteParameters.IMAGE_WIDTH,
						WebsiteParameters.IMAGE_HEIGHT);
				ImageIO.write(img, extension, new File(storedPath));

				this.parametersMap.put(fieldName, fileName);
				tmpFile.delete(); // File is anymore useful
			}
			catch (IllegalArgumentException e)
			{
				// file is not an image
				item.delete();
				throw new FileUploadException(Errors.BadPicture.toString());
			}

		}
		catch (Exception e)
		{

			if (e instanceof FileUploadException)
			{
				throw new FileUploadException(e.getMessage());
			}
			else
			{

				e.printStackTrace();
			}
		}

	}

	private void processFormField(HttpServletRequest request, FileItem formField)
	{
		// session needed in order to get the current user name

		String value = formField.getString();
		String name = formField.getFieldName();

		if (value != null)
		{
			if (value.equals("") || value.matches("\\<.*\\>"))
			{
				value = null;
			}
		}

		this.parametersMap.put(name, value);
	}

	/**
	 * return null if the file does not exist, its name if it does. if the file
	 * is too big a FileUploadException will be thrown
	 * 
	 * @param item
	 * @return
	 * @throws FileUploadException
	 */
	private String checkSizeAndExistency(FileItem item)
			throws FileUploadException
	{
		String fileName = FilenameUtils.getName(item.getName());

		if (fileName.length() <= 0)
		{
			// No file has been uploaded
			return null;
		}
		else if (item.getSize() > WebsiteParameters.FILE_MAX_SIZE)
		{
			// check if file is of a good size
			item.delete();
			throw new FileUploadException(Errors.BadSize.toString());
		}

		return fileName;
	}

}
